Skip to content

Fix anonymous-type lambda early-return emitting unresolvable cast#3752

Open
jakobhellermann wants to merge 2 commits into
icsharpcode:masterfrom
jakobhellermann:fix-anonymous-early-return
Open

Fix anonymous-type lambda early-return emitting unresolvable cast#3752
jakobhellermann wants to merge 2 commits into
icsharpcode:masterfrom
jakobhellermann:fix-anonymous-early-return

Conversation

@jakobhellermann
Copy link
Copy Markdown

Fixes #3751

Problem

When a lambda's inferred return type contains an anonymous type and one branch returns null, the decompiler emitted an explicit cast such as return (IEnumerable<<>f__AnonymousType0<int>>)null;, which is invalid C#.

Solution

Skip the cast in IsPossibleLossOfTypeInformation for null literals whenever the expected type contains an anonymous type:
null is implicitly convertible to any reference type, so no cast is needed, and the anonymous type has no nameable form to cast to anyway.

When a lambda's inferred return type contains an anonymous type and one
branch returns null, the decompiler emitted an explicit cast such as
`return (IEnumerable<<>f__AnonymousType0<int>>)null;`, which is invalid C#.

Skip the cast in IsPossibleLossOfTypeInformation for null literals whenever
the expected type contains an anonymous type:
null is implicitly convertible to any reference type, so no cast is needed,
and the anonymous type has no nameable form to cast to anyway.

Fixes icsharpcode#3751
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a decompiler edge case where lambdas/anonymous methods with an inferred return type involving an anonymous type could emit an explicit cast on null (e.g., return (<>f__AnonymousType0<int>)null;), which is not valid C# syntax. The change prevents emitting such casts when the expected type contains an anonymous type, and adds a regression test for the reported scenario.

Changes:

  • Adjusted StatementBuilder.IsPossibleLossOfTypeInformation() to not treat null as requiring an explicit cast when the expected type contains an anonymous type.
  • Added a new pretty test case reproducing Issue #3751.
  • Registered the new Issue3751 test in PrettyTestRunner.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs Skips explicit casts for null returns when the expected type contains an anonymous type, preventing unnameable cast emission.
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3751.cs Adds a regression test source that would previously decompile to an invalid cast to an anonymous type.
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs Registers the new Issue3751 pretty test to run across the default compiler option matrix.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ICSharpCode.Decompiler/CSharp/StatementBuilder.cs Outdated
@jakobhellermann
Copy link
Copy Markdown
Author

CI seems to have failed during Upload Test Logs. Any idea why? or can you retry the action?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Decompilation of anonymous-type returning lambda with early return emits <>f__AnonymousTypeN

3 participants